home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
cool
/
ge_cool.lha
/
GE_COOL2.1
/
cpp
/
typecase.c
< prev
Wrap
C/C++ Source or Header
|
1992-04-13
|
5KB
|
205 lines
/*
Copyright (C) 1990 Texas Instruments Incorporated.
Permission is granted to any individual or institution to use, copy, modify,
and distribute this software, provided that this complete copyright and
permission notice is maintained, intact, in all copies and supporting
documentation.
Texas Instruments Incorporated provides this software "as is" without
express or implied warranty.
*
* Created: MJF 08/20/90 -- Initial design and implementation.
*
* The TYPE_CASE defmacro
*
* To use, declare:
* #pragma defmacro TYPE_CASE "type_case" delimiter=}
*
* TYPECASE (generic_ptr) { case_statements }
* case_statements = case sym_name : statements [case_statements]
*
* THE TYPE_CASE macro is analogous to the C++ switch statment
* It gathers all possible cases and allows the user to symbolically
* dispatch on the type of object represented by the case statements.
*
* Generic* g;
* TYPE_CASE (g) {
* case Vector: // If the object is a vector
* .... // Do something for Vector
* break;
* case List: // If the object is a list
* .... // Do something for List
* break;
* default: // Else do the rest
* ....
* }
*
* expands to:
*
* Generic* g;
* static Symbol* switch_symbols_g[3] = {SYM(Vector), SYM(List), NULL};
* switch (g->select_type_of(switch_symbols_g)) {
* case 0: // If the object is a vector
* .... // Do something for Vector
* break;
* case 1: // If the object is a list
* .... // Do something for List
* break;
* default: // Else do the rest
* ....
* }
*
*/
#include "defmacio.h"
#define MAXCASE 64
#define MAXBUF 512
typedef struct case_body {
int default_case;
char* body;
} Case_Body;
typecase(argc, argv)
int argc;
char* argv[];
{
char junk[MAXBUF];
char c;
char* macname; /* TYPE_CASE is the macro name */
char* genptr; /* the name of a generic pointer */
char* name;
char *str1, *str2;
Case_Body cbody[30];
int ncases, i;
char* syms[30]; /* Contains all symbols in TYPE_CASE */
int nsyms;
char body[512]; /* Contains body of each case */
int done;
if(copytoken(junk) == NULL) /* Skip macro name */
return(1);
macname = savestring(junk);
c = skip_blanks();
if(c != '(') {
fprintf(stderr, "%s: '%c' found instead of '('\n", macname, c);
return 1;
}
done = 0;
nsyms = ncases = 0;
name = scan_next(' ');
c = getchar();
if (c != ')') {
fprintf(stderr, "%s: '%c' found instead of ')' after %s\n",
macname, c, name);
return 1;
}
genptr = savestring(name);
c = skip_blanks();
if (c != '{') {
fprintf(stderr, "%s: '%c' found instead of '{' after %s\n",
macname, c, genptr);
return 1;
}
name = scan_list(' ');
for (i=0;i< MAXCASE;i++) {
str2 = body;
if (name == NULL) return 1;
if(!strcmp(name, "case")) { /* case Vector: */
cbody[i].default_case = 0;
cbody[i].body = 0;
name = scan_next(' ');
c = skip_blanks();
if (c != ':') {
fprintf(stderr, "%s: Missing ':' after '%s'\n",
macname, name);
return 1;
}
syms[nsyms++] = savestring(name);
} else if (!strcmp(name, "default")) { /* default: */
c = getchar();
if (c != ':') {
fprintf(stderr, "%s: Missing ':' after '%s'\n",
macname, name);
return 1;
}
cbody[i].default_case = 1;
cbody[i].body = 0;
} else {
str1 = name;
while (*str1 != '\0') *str2++ = *str1++;
}
/* collect body of case */
for (;;) {
c = getchar();
while (!isalnum(c) && c !=EOF) {
*str2++ = c;
c = getchar();
}
if (c == EOF) { /* TYPE_CASE is done */
done = 1;
break;
} else unget();
name = scan_list(' ');
if (!strcmp(name,"case") || !strcmp(name,"default")) break;
str1 = name;
while (*str1 != '\0') *str2++ = *str1++;
}
ncases++;
*str2 = EOS;
cbody[i].body = savestring(body);
if (done) break;
}
/* expand TYPE_CASE macro*/
sprintf(junk, "\n{\nstatic Symbol* switch_symbols_%s[%d] = {",
genptr, nsyms+1);
puts(junk); /* start of SYM list */
for (i = 0; i < nsyms; i++) { /* output each SYM name */
sprintf(junk,"SYM(%s),", syms[i]);
puts(junk);
}
puts("NULL};\n"); /* end of SYM list */
sprintf(junk, "switch(%s->select_type_of(switch_symbols_%s)) {\n",
genptr, genptr);
puts(junk); /* start of switch statement */
for (i = 0; i< ncases; i++) { /* output body for each case */
if (cbody[i].default_case)
sprintf(junk, "default:", i);
else
sprintf(junk, "case %d:", i);
puts(junk);
if (cbody[i].body)
puts(cbody[i].body);
}
puts ("\n} \n"); /* end of switch statement */
free(macname);
return 0;
}